/* sdcard_spi_port.c */
#include "fsl_common.h"
#include "fsl_clock.h"
#include "fsl_gpio.h"

#include "sdcard_spi.h"

void spi_init(void);
uint8_t spi_xfer(uint8_t tx_dat);
void spi_assert_cs(bool enable);

SDC_SPIHwDrv_T sdcard_spi_spi_hw_driver =
{
    .SPI_InitHwFunc = spi_init,
    .SPI_SwapByteFunc = spi_xfer,
    .SPI_AssertCsFunc = spi_assert_cs
};

/* pins:
 * tx : PTD2/SPI0_MOSI
 * rx : PTD3/SPI0_MISO
 * clk: PTD1/SPI0_SCK
 * cs : PTD0/SPI0_PCS0
 */

void spi_init(void)
{
    /* pin mux. */
    CLOCK_EnableClock(kCLOCK_PortD);
    PORTD->PCR[0] = PORT_PCR_MUX(1); /* PTD0: SPI0_PCS0, GPIO模式. */
    PORTD->PCR[1] = PORT_PCR_MUX(2); /* PTD1: SPI0_CLK. */
    PORTD->PCR[2] = PORT_PCR_MUX(2); /* PTD2: SPI0_MOSI */
    PORTD->PCR[3] = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; /* PTD3: SPI0_MISO. */

    /* gpio for cs pin. */
    gpio_pin_config_t gpio_pin_config;
    gpio_pin_config.pinDirection = kGPIO_DigitalOutput;
    gpio_pin_config.outputLogic = 1u;
    GPIO_PinInit(GPIOD, 0u, &gpio_pin_config);

    /* spi0. */
    /* spi0使用bus clock. */
    CLOCK_EnableClock(kCLOCK_Spi0);
    SPI0->C1 = SPI_C1_SPE_MASK /* enable spi. */
             | SPI_C1_MSTR_MASK /* master mode. */
             | SPI_C1_CPOL(0) /* clock polarity. */
             | SPI_C1_CPHA(0) /* phase polarity. */
             ;
    SPI0->C2 = 0u;
    SPI0->BR = SPI_BR_SPPR(2) | SPI_BR_SPR(2); /* div = 3x8. busclk = 24mhz, baudrate = 1mhz. */

}

uint8_t spi_xfer(uint8_t tx_dat)
{
    uint8_t rx_dat;
    while (! (SPI0->S & SPI_S_SPTEF_MASK) )
    {}
    SPI0->D = tx_dat;
    while (! (SPI0->S & SPI_S_SPRF_MASK) )
    {}
    rx_dat = SPI0->D;

#if 0
    for (uint32_t i = 0u; i < 5000u; i++)
    {
        asm("nop");
    }
#endif
    return rx_dat;
}

void spi_assert_cs(bool enable)
{
    GPIO_WritePinOutput(GPIOD, 0u, (enable ? 0u: 1u) );
}

/* EOF. */

